package com.bjb.vr.common.utils;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Author: HuJingBo
 * @Date: 2019/12/18 16:55
 * @Description: 缓存工具加载类
 */
public class LoadingCacheUtil<K, V> {

    /**
     * 加载缓存线程池
     */
    public static final ExecutorService REFRESH_EXECUTOR = new ThreadPoolExecutor(1, Integer.MAX_VALUE, 1, TimeUnit.MINUTES, new LinkedBlockingQueue(), new ThreadPoolExecutor.CallerRunsPolicy());

    /**
     * 自定义加载时间（分钟）
     *
     * @param maximumSize
     * @param cacheLoader
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K, V> LoadingCache<K, V> asyncReloadMin(Long maximumSize, long duration, CacheLoader cacheLoader) {
        return asyncReload(maximumSize, cacheLoader, duration, TimeUnit.MINUTES);
    }

    /**
     * 自定义加载时间
     *
     * @param maximumSize
     * @param cacheLoader
     * @param duration
     * @param unit
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K, V> LoadingCache<K, V> asyncReload(Long maximumSize, CacheLoader cacheLoader, long duration, TimeUnit unit) {
        CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder();
        builder.concurrencyLevel(Runtime.getRuntime().availableProcessors());
        builder.recordStats();
        if (maximumSize != null) {
            builder.maximumSize(maximumSize);
        }
        return builder.refreshAfterWrite(duration, unit).build(CacheLoader.asyncReloading(cacheLoader, REFRESH_EXECUTOR));
    }

    /**
     * 立即加载
     *
     * @param maximumSize
     * @param cacheLoader
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K, V> LoadingCache<K, V> justLoad(Long maximumSize, CacheLoader cacheLoader) {
        CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder();
        builder.concurrencyLevel(Runtime.getRuntime().availableProcessors());
        builder.recordStats();
        if (maximumSize != null) {
            builder.maximumSize(maximumSize);
        }
        return builder.build(cacheLoader);
    }
}
